﻿ #define  _CRT_SECURE_NO_WARNINGS

#include<stdio.h>

//C语⾔中，递归就是函数⾃⼰调⽤⾃⼰
//把⼀个⼤型复杂问题层层转化为⼀个与原问题相似，但规模较⼩的⼦问题来求解；
//直到⼦问题不能再被拆分，递归就结束了。所以递归的思考⽅式就是把⼤事化⼩的过程。
//递归中的递就是递推的意思，归就是回归的意思

//递归在书写的时候，有2个必要条件：
// 递归存在限制条件，当满⾜这个限制条件的时候，递归便不再继续。
// 每次递归调⽤之后越来越接近这个限制条件。

//求n的阶乘

//int jie(int a)
//{
//	if (a == 0)
//		return 1;
//	else
//		return a * jie(a - 1);
//}
//
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	int a = jie(n);
//	printf("n的阶乘是：%d", a);
//	return 0;
//}

//输⼊⼀个整数m，打印这个按照顺序打印整数的每⼀位。
//⽐如：
//输⼊：1234 输出：1 2 3 4
//输⼊：520 输出：5 2 0
//
//print(int a)
//{
//	if (a > 9)//限制条件
//	{
//		print(a / 10);//使每一次递归都趋向限制条件
//	}
//	printf("%d ",a % 10);
//}
//
//int main()
//{
//	int a = 0;
//	scanf("%d", &a);
//	print(a);
//	return 0;
//}



//int main()
//{
//	int a = -10;
//	//-10是存放在a中，a是整型变量，是4个字节，32bit位
//	//10000000000000000000000000001010 - 原码
//	//11111111111111111111111111110101 - 反码
//	//11111111111111111111111111110110 - 补码
//	//
//
//	int b = 10;
//	//00000000000000000000000000001010 - 原码
//	//00000000000000000000000000001010 - 反码
//	//00000000000000000000000000001010 - 补码
//
//	return 0;
//}

//1-1
//1 + (-1)
//00000000000000000000000000000001
//11111111111111111111111111111111 
//00000000000000000000000000000000
//  
//10000000000000000000000000000001
//11111111111111111111111111111110
//11111111111111111111111111111111

//
//int main()
//{
//	int a = 6;
//	int b = (a << 1);
//
//	printf("%d\n", b);
//	printf("%d\n", a);
//
//
//	return 0;
//}


//
//int main()
//{
//	int a = -6;
//	//10000000000000000000000000000110
//	//11111111111111111111111111111001
//	//11111111111111111111111111111010  ---> -6的补码
//	//11111111111111111111111111110100  -- b中得到的补码
//	//10000000000000000000000000001011
//	//10000000000000000000000000001100 -> -12
//
//	int b = (a << 1);
//
//	printf("%d\n", b);//-12
//	printf("%d\n", a);//-6
//
//
//	return 0;
//}


//-1
//10000000000000000000000000000001
//11111111111111111111111111111110
//11111111111111111111111111111111  -- -1的补码

//int main()
//{
//	int num = -1;
//	//num = num >> 1;
//	
//	num >>= 1;//复合赋值
//
//	//int b = num >> 1;
//	//printf("%d\n", b);
//
//	return 0;
//}
//


//int main()
//{
//	int a = 6;
//	a <<= 1;
//	printf("%d\n", a);
//	return 0;
//}



//位操作符：& 、 | 、 ^ 、~
//& 按（二进制）位与


//& 按(2进制)位与

//int main()
//{
//	int a = 3;
//	int b = -5;
//
//	int c = a & b;
//	//00000000000000000000000000000011 3的补码
//	//10000000000000000000000000000101
//	//11111111111111111111111111111010
//	//11111111111111111111111111111011 -5的补码
//	//00000000000000000000000000000011
//	//11111111111111111111111111111011
//	//00000000000000000000000000000011 -补码
//	printf("%d\n", c);
//
//	return 0;
//}


// | 按位或
//int main()
//{
//	int a = 3;
//	int b = -5;
//
//	int c = a | b;
//	//00000000000000000000000000000011 3的补码
// 
//	//10000000000000000000000000000101
//	//11111111111111111111111111111010
//	//11111111111111111111111111111011 -5的补码
// 
//	//00000000000000000000000000000011
//	//11111111111111111111111111111011
// 
//	//11111111111111111111111111111011  补码（负数的补码要转成原码）除符号位取反加1
//	//10000000000000000000000000000100
//	//10000000000000000000000000000101 -5
//	printf("%d\n", c);
//
//	return 0;
//}


//^   按(2进制)位异或
//  异或：相同为0，相异位1
//int main()
//{
//	int a = 3;
//	int b = -5;
//
//	int c = a ^ b;
//	//00000000000000000000000000000011 3的补码
//	//10000000000000000000000000000101 -5的原码
//	//11111111111111111111111111111010
//	//11111111111111111111111111111011 -5的补码
//	// 
//	//00000000000000000000000000000011
//	//11111111111111111111111111111011
//	//11111111111111111111111111111000 -补码
//	//10000000000000000000000000000111
//	//10000000000000000000000000001000
//
//	printf("%d\n", c);//-8
//
//	return 0;
//}


//int main()
//{
//	int a = 0;
//	int b = ~a;
//	//00000000000000000000000000000000
//	//11111111111111111111111111111111 -- 补码
//	//10000000000000000000000000000000
//	//10000000000000000000000000000001
//	printf("%d\n", b);//-1
//
//	return 0;
//}

//逗号表达式，从左向右依次执⾏。整个表达式的结果是最后⼀个表达式的结果。

//⾃定义的数据类型：结构体

//指针类型作用：
//1 解引用时访问几个字节
//2 指针加减时移动几个字节



//int main()
//{
//	const int a = 10;//a具有了常属性（不能被修改了）
//	//a 是不是常量呢？虽然a是不能被修改的，但是本质上还是变量
//	//常变量
//	// 
//	//a = 20;
//	//在C++ 中const修饰的变量就是常量
//	//
//	int arr[a];
//	printf("%d\n", a);
//
//	return 0;
//}
//
//int main()
//{
//	const int a = 0;
//	a = 2;//报错
//	return 0;
//}

//int main()
//{
//	const int a = 0;
//	int* b = &a;
//	*b = 2;
//	printf("%d", a);//修改成功  b拿到n的地址就能修改n，这样就打破了const的限制
//	return 0;
//}


//int main()
//{
//	int a = 10;/
//	int b = 20;
//
//	int  * const p = &a;
//	//p = &b;//err
//	*p = 100;
//	printf("%d\n", a);
//
//	//const 修饰指针变量的时候，放在*的右边
//	//const ******************************限制的是指针变量本身，指针变量不能再指向其他变量了*************************
//	//但是可以通过指针变量，修改指针变量指向的内容
//	//
//	return 0;
//}


//int main()
//{
//	int a = 10;
//	int b = 20;
//	int const * p = &a;
//	//p = &b;//ok
//	//*p = 100;//err
//	//const 修饰指针变量时，放在*的左边，*********************限制的是：指针指向的内容，不能通过指针来修改指向的内容******************************
//	//但是可以修改指针变量本身的值（修改的指针变量的指向）
//
//	return 0;
//}

//int main()
//{
//	int a = 10;
//	int b = 100;
//	int const * const p = &a;
//	p = &b;//err
//	*p = 0;//err
//	return 0;
//}

//总结
//const 放在左边 即 const *p  限制内容（*p）（*p即p指针解引用后的内容）  放在右边 即 * const p  限制内容 p（p是地址）


//因为数组在内存中是连续存放的，只要知道第⼀个元素的地址，顺藤摸⽠就能找到后⾯的所有元素。

//利用地址打印数组内容

//int main()
//{
//	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//	int* p = &arr[0];
//	int i = 0;
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *p);
//		p++;
//	}
//	return 0;
//}

//int main()
//{
//	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//	int* p = &arr[0];
//	int i = 0;
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *(p+i));
//	}
//	return 0;
//}

//指针-指针计算的前提条件一定是：两个指针指向了同一块空间！!!

//int main()
//{
//	int arr[10] = { 0 };
//	printf("%zd\n", &arr[0] - &arr[9]);
//	printf("%zd\n", &arr[9] - &arr[0]);
//
//	return 0;
//}

//int my_strlen(char* str)
//{
//	int count = 0;
//	while (*str != '\0')
//	{
//		count++;
//		str++;
//	}
//	return count;
//}

//int my_strlen(char* str)
//{
//	char* start = str;
//	while (*str != '\0')
//	{
//		str++;
//	}
//	return str - start;
//}

//int main()
//{
//	//strlen -  求字符串长度的, strlen统计的是字符串中\0之前的字符个数
//	char arr[] = "abcdef";
//	//[a b c d e f \0]
//
//	int len = my_strlen(arr);//数组名arr是数组首元素的地址 arr == &arr[0]
//	printf("%d\n", len);
//
//	return 0;
//}

//int main()
//{
//	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//	int sz = sizeof(arr) / sizeof(arr[0]);//10
//	int* p = arr;//&arr[0]
//
//	while (p < arr + sz)//指针的关系运算
//	{
//		printf("%d ", *p);
//		p++;
//	}
//	return 0;
//}

//写一个函数，交换两个整数的内容
//
//void Swap1(int x, int y)
//{
//	int tmp = x;
//	x = y;
//	y = tmp;
//}
//
//int main()
//{
//	int a = 10;
//	int b = 20;
//	printf("交换前:a=%d b=%d\n", a, b);
//	//当实参传递给形参的时候，形参是实参一份临时拷贝
//	//对形参的修改不会影响实参的
//
//	Swap1(a, b); //传值调用
//	printf("交换后:a=%d b=%d\n", a, b);
//
//	return 0;
//}

//Swap(int* x, int* y)
//{
//	int z = 0;
//	z = *x;
//	*x = *y;
//	*y = z;
//}
//
//int main()
//{
//	int a = 10;
//	int b = 20;
//	printf("交换前:a=%d b=%d\n", a, b);
//
//	Swap(&a, &b);//传址调用
//	printf("交换后:a=%d b=%d\n", a, b);
//
//	return 0;
//}